package cn.ztuo.bitrade.controller;

import cn.ztuo.bitrade.constant.CommonStatus;
import cn.ztuo.bitrade.constant.PageModel;
import cn.ztuo.bitrade.constant.TransactionType;
import cn.ztuo.bitrade.core.Convert;
import cn.ztuo.bitrade.entity.*;
import cn.ztuo.bitrade.entity.Short;
import cn.ztuo.bitrade.entity.transform.AuthMember;
import cn.ztuo.bitrade.service.*;
import cn.ztuo.bitrade.system.CoinExchangeFactory;
import cn.ztuo.bitrade.util.CoBoUtils;
import cn.ztuo.bitrade.util.FiworkWalletUtil;
import cn.ztuo.bitrade.util.MessageResult;
import cn.ztuo.bitrade.util.PredicateUtils;
import com.alibaba.fastjson.JSONObject;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.BooleanExpression;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.servlet4preview.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static cn.ztuo.bitrade.constant.SysConstant.SESSION_MEMBER;

@RestController
@RequestMapping("/asset")
@Slf4j
public class AssetController extends BaseController {
    @Autowired
    private MemberWalletService walletService;
    @Autowired
    private MemberTransactionService transactionService;
    @Autowired
    private CoinExchangeFactory coinExchangeFactory;
    @Autowired
    private KafkaTemplate kafkaTemplate;
    @Autowired
    private LockPositionRecordService lockPositionRecordService;
    @Autowired
    private CoinService coinService;
    @Autowired
    private LocaleMessageSourceService sourceService;
    @Autowired
    private MemberWalletService memberWalletService;
    @Autowired
    private CoBoUtils coBoUtils;
    @Autowired
    private ShortService shortService;
    @Autowired
    private IeoOdfrecordService ieoOdfrecordService;


    /**
     * 用户钱包信息
     *
     * @param member
     * @return
     */
    @RequestMapping("wallet")
    public MessageResult findWallet(@SessionAttribute(SESSION_MEMBER) AuthMember member) {
        List<MemberWallet> wallets = walletService.findAllByMemberId(member.getId());
        wallets.forEach(wallet -> {
            CoinExchangeFactory.ExchangeRate rate = coinExchangeFactory.get(wallet.getCoin().getUnit());
            if (rate != null) {
                wallet.getCoin().setUsdRate(rate.getUsdRate());
                wallet.getCoin().setCnyRate(rate.getCnyRate());
                wallet.getCoin().setSgdRate(rate.getSgdRate());
//                if(StringUtils.isNotBlank(wallet.getCoin().getColdWalletAddress())){
//                    wallet.setAddress(wallet.getCoin().getColdWalletAddress());
//                }
                if(StringUtils.isNotBlank(wallet.getCoin().getExtraAddress())){
                    wallet.setExtraAddress(wallet.getCoin().getExtraAddress());
                }
            } else {
                log.info("unit = {} , rate = null ", wallet.getCoin().getUnit());
            }
        });
        MessageResult mr = MessageResult.success("success");
        mr.setData(wallets);
        return mr;
    }


    @PostMapping("walletInfo")
    public MessageResult walletInfo(@SessionAttribute(SESSION_MEMBER) AuthMember member, String unit){
        HashMap<String, BigDecimal> map = new HashMap<>();
        BigDecimal number = BigDecimal.ZERO;
        if(unit.trim().equals("ODF")) {
            Short shorts = shortService.findByMemberIdAndStatus(member.getId(), 1L);
            if(shorts!=null) {
                number = number.add(shorts.getFreed());
            }
            BigDecimal amount = ieoOdfrecordService.sumAmount(member.getId());
            if(amount!=null && amount.compareTo(BigDecimal.ZERO)>0){
                number = number.add(amount);
            }
        }
        map.put("coinBalance",number);
        return MessageResult.getSuccessInstance("success",map);
    }

    /**
     * 查询特定类型的记录
     *
     * @param member
     * @param pageNo
     * @param pageSize
     * @param type
     * @return
     */
    @RequestMapping("transaction")
    public MessageResult findTransaction(@SessionAttribute(SESSION_MEMBER) AuthMember member, int pageNo, int pageSize, TransactionType type, String symbol,
                                         String startTime, String endTime) throws Exception {
        Page page = transactionService.queryByMember(member.getId(), pageNo, pageSize, type, startTime, endTime, symbol);
        return success(page);
    }

    /**
     * 查询所有记录
     *
     * @param member
     * @param pageNo
     * @param pageSize
     * @return
     */
    @RequestMapping("transaction/all")
    public MessageResult findTransaction(
            @SessionAttribute(SESSION_MEMBER) AuthMember member,
            HttpServletRequest request,
            int pageNo,
            int pageSize,
            @RequestParam(value = "symbol", required = false) String symbol) throws ParseException {
        TransactionType type = null;
        if (StringUtils.isNotEmpty(request.getParameter("type"))) {
            type = TransactionType.valueOfOrdinal(Convert.strToInt(request.getParameter("type"), 0));
        }
        String startDate = "";
        String endDate = "";
        if (StringUtils.isNotEmpty(request.getParameter("dateRange"))) {
            String[] parts = request.getParameter("dateRange").split("~");
            startDate = parts[0].trim();
            endDate = parts[1].trim();
        }
        return success(transactionService.queryByMember(member.getId(), pageNo, pageSize, type, startDate, endDate, symbol));
    }

    @RequestMapping("wallet/{symbol}")
    public MessageResult findWalletBySymbol(@SessionAttribute(SESSION_MEMBER) AuthMember member, @PathVariable String symbol) {
        MessageResult mr = MessageResult.success("success");
        mr.setData(walletService.findByCoinUnitAndMemberId(symbol, member.getId()));
        return mr;
    }

    /**
     * 使用infura获取充值地址
     * @param member
     * @param unit
     * @param USDTType
     * @return
     */
    @RequestMapping("wallet/reset-address")
    public MessageResult resetWalletAddress(@SessionAttribute(SESSION_MEMBER) AuthMember member, String unit, String USDTType) {
        try {
            if(unit.toUpperCase()=="ODF") return MessageResult.error("地址已生成");
            JSONObject json = new JSONObject();
            json.put("uid", member.getId());
            if(unit==null || unit.equals("")) MessageResult.error("币种不存在");
            MemberWallet memberWallet = memberWalletService.findByCoinUnitAndMemberId(unit, member.getId());
            //根据 币种名称 查询币种信息配置表
            Coin coin = coinService.findByUnit(unit);
            //判断 币种信息是否为空
            Assert.notNull(coin, "币种信息表 null");
            String coinNamePrefix = "";
            if (StringUtils.isNotEmpty(coin.getPrefix())) {
                coinNamePrefix = coin.getPrefix() + "_";
            } else if (("USDT".equals(coin.getUnit()))) {
                if ("ERC20".equals(USDTType)) {
                    coinNamePrefix = "ETH_";
                } else if ("OMNI".equals(USDTType)) {
                    coinNamePrefix = "BTC_";
                }
            }
            Address info = FiworkWalletUtil.getEthAddressForCollection(String.valueOf(member.getId()));
            //获得地址
            String address = info.getAddress();
            String privatekey = info.getPrivateKey();
            if ((StringUtils.isNotEmpty(coin.getPrefix()) && "ETH".equals(coin.getPrefix())) || (USDTType != null && "ERC20".equals(USDTType)) || "ETH".equals(coin.getName())) {
                List<Coin> ethCoins = coinService.findByPrefix("ETH");
                ethCoins.forEach(ethcoin -> {
                    MemberWallet byCoinAndMemberId = memberWalletService.findByCoinAndMemberId(ethcoin, member.getId());
                    if (byCoinAndMemberId != null) {
                        byCoinAndMemberId.setAddress(address);
                        byCoinAndMemberId.setPrivatekey(privatekey);
                        memberWalletService.save(byCoinAndMemberId);
                    }
                });
            } else {
                // 区分ETH 和 BTC
                if ("BTC_".equals(coinNamePrefix)) {
                    memberWallet.setExtraAddress(address);
                } else {
                    memberWallet.setAddress(address);
                }
                memberWalletService.save(memberWallet);
            }
            return MessageResult.success("获取地址成功!",address);
        } catch (Exception e) {
            e.printStackTrace();
            return MessageResult.error("获取币种" + unit + "地址错误.请联系客服人员!!");
        }
    }

    /**
     * COBO获取地址
     * @param member
     * @return
     */
//    @RequestMapping("wallet/reset-address")
//    public MessageResult resetWalletAddress(@SessionAttribute(SESSION_MEMBER) AuthMember member, String unit, String USDTType) {
//        try {
//            JSONObject json = new JSONObject();
//            json.put("uid", member.getId());
//            MemberWallet memberWallet = memberWalletService.findByCoinUnitAndMemberId(unit, member.getId());
//            //根据 币种名称 查询币种信息配置表
//            Coin coin = coinService.findByUnit(unit);
//            log.info("获取的币种信息表={}", coin);
//            //判断 币种信息是否为空
//            Assert.notNull(coin, "币种信息表 null");
//            //调用cobo
//            TreeMap<String, Object> params = new TreeMap<>();
//
//            String coinNamePrefix = "";
//            if (StringUtils.isNotEmpty(coin.getPrefix())) {
//                coinNamePrefix = coin.getPrefix() + "_";
//            } else if (("USDT".equals(coin.getUnit()))) {
//                if ("ERC20".equals(USDTType)) {
//                    coinNamePrefix = "ETH_";
//                } else if ("OMNI".equals(USDTType)) {
//                    coinNamePrefix = "BTC_";
//                }
//            }
//
//            String newCoinUnit = coinNamePrefix + coin.getUnit();
//
//            params.put("coin", newCoinUnit);
//            JSONObject newaddre = coBoUtils.newaddre(params);
//            log.info("获得={},的地址的参数={}", coin.getUnit(), newaddre.toJSONString());
//            JSONObject result = newaddre.getJSONObject("result");
//            //获得地址
//            String address = result.getString("address");
//
//            if ((StringUtils.isNotEmpty(coin.getPrefix()) && "ETH".equals(coin.getPrefix())) || (USDTType != null && "ERC20".equals(USDTType)) || "ETH".equals(coin.getName())) {
//                List<Coin> ethCoins = coinService.findByPrefix("ETH");
//                ethCoins.forEach(ethcoin -> {
//                    MemberWallet byCoinAndMemberId = memberWalletService.findByCoinAndMemberId(ethcoin, member.getId());
//                    if (byCoinAndMemberId != null) {
//                        byCoinAndMemberId.setAddress(address);
//                        memberWalletService.save(byCoinAndMemberId);
//                    }
//                });
//            } else {
//                // 区分ETH 和 BTC
//                if ("BTC_".equals(coinNamePrefix)) {
//                    memberWallet.setExtraAddress(address);
//                } else {
//                    memberWallet.setAddress(address);
//                }
//                memberWalletService.save(memberWallet);
//                //这里不使用kafka处理
//                //kafkaTemplate.send("reset-member-address", unit, json.toJSONString());
//            }
//            return MessageResult.success("获取地址成功!");
//        } catch (Exception e) {
//            e.printStackTrace();
//            return MessageResult.error("获取币种" + unit + "地址错误.请联系客服人员!!");
//        }
//    }



    @PostMapping("lock-position")
    public MessageResult lockPositionRecordList(@SessionAttribute(SESSION_MEMBER) AuthMember member,
                                                @RequestParam(value = "status", required = false) CommonStatus status,
                                                @RequestParam(value = "coinUnit", required = false) String coinUnit,
                                                PageModel pageModel) {
        ArrayList<BooleanExpression> booleanExpressions = new ArrayList<>();
        if (status != null) {
            booleanExpressions.add(QLockPositionRecord.lockPositionRecord.status.eq(status));
        }
        if (coinUnit != null) {
            Coin coin = coinService.findByUnit(coinUnit);
            if (coin == null) {
                return MessageResult.error(sourceService.getMessage("COIN_ILLEGAL"));
            }
            booleanExpressions.add(QLockPositionRecord.lockPositionRecord.coin.eq(coin));
        }
        booleanExpressions.add(QLockPositionRecord.lockPositionRecord.memberId.eq(member.getId()));
        Predicate predicate = PredicateUtils.getPredicate(booleanExpressions);
        Page<LockPositionRecord> lockPositionRecordList = lockPositionRecordService.findAll(predicate, pageModel);
        MessageResult result = MessageResult.success();
        result.setData(lockPositionRecordList);
        return result;
    }
}
